package cn.ecommerce.course.module.users.controller.app.users.vo;


import cn.ecommerce.course.module.users.dal.dataobject.users.RoleDO;
import cn.ecommerce.course.module.users.dal.dataobject.users.UsersDO;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 登录用户信息VO（View Object），实现Spring Security的UserDetails接口
 * 用于封装Spring Security认证所需的用户核心信息，是认证流程中的关键对象
 *
 * 说明：
 * - 该类是Spring Security与业务系统用户信息之间的"桥梁"
 * - 当用户登录时，Spring Security会通过该类获取用户的账号、密码、权限等信息进行认证授权
 * - 命名中的"VO"表示其主要用于系统内部数据传递（而非直接暴露给前端）
 */
@Data
@NoArgsConstructor
public class SecurityUserVO implements UserDetails {

    // 可以根据业务需求添加自定义字段，例如：
    // private Long id; // 用户ID
    // private String nickName; // 用户昵称
    // private String avatar; // 头像URL
    // private String email; // 邮箱
    // ... 其他需要在认证后保存的用户信息
    private UsersDO userDO; // 用户DO对象
    // 角色列表
    private List<RoleDO> roleList;

    //构建有参构造函数，用于初始化用户信息
    public SecurityUserVO(UsersDO userDO) {
        this.userDO = userDO;
//        this.roleList = roleList;
    }
    /**
     * 获取用户拥有的权限集合
     * Spring Security会根据该方法返回的权限集合，判断用户是否有权限访问某个资源
     *
     * @return 权限集合，每个元素为GrantedAuthority类型（通常是角色或具体权限）
     *         例如：List.of(new SimpleGrantedAuthority("ROLE_ADMIN"), new SimpleGrantedAuthority("user:query"))
     */
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        // 此处默认返回空集合，实际业务中需根据用户角色查询并返回对应的权限
        // 例如：从数据库查询用户角色，转换为GrantedAuthority集合返回

        // 创建一个集合存储权限信息
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();

        // 判空：如果角色列表为空，直接返回空集合
        if (roleList == null || roleList.isEmpty()) {
            return authorities;
        }

        // 循环遍历角色列表
        for (RoleDO role : roleList) {
            // 1. 获取角色编码（如 "ADMIN"、"STUDENT"）
            String roleCode = role.getRoleCode();
            // 2. 按照 Spring Security 要求，添加 "ROLE_" 前缀（如 "ROLE_ADMIN"）
            // 3. 创建 SimpleGrantedAuthority 对象，添加到集合中
            authorities.add(new SimpleGrantedAuthority(roleCode));
        }

        // 返回最终的权限集合
        return authorities;
    }

    /**
     * 获取用户密码
     * Spring Security在认证时，会将该方法返回的密码与用户输入的密码进行比对
     * （通常需返回数据库中存储的加密后的密码，如BCrypt加密结果）
     *
     * @return 数据库中存储的用户密码（加密后）
     */
    @Override
    public String getPassword() {
        // 此处默认返回空字符串，实际业务中需返回当前用户的加密密码
        return userDO.getPassword();
    }

    /**
     * 获取用户名（登录账号）
     * Spring Security在认证时，会使用该方法返回的用户名作为认证的账号标识
     * （通常对应数据库中的登录账号，如user_name字段）
     *
     * @return 用户登录账号（唯一）
     */
    @Override
    public String getUsername() {
        // 返回当前用户的登录账号
        return userDO != null ? userDO.getAccount() : "";
    }
    /**
     * 账号是否未过期
     * Spring Security会检查该方法返回值，若为false则拒绝登录（提示账号过期）
     *
     * @return true表示账号未过期，false表示已过期
     */
    @Override
    public boolean isAccountNonExpired() {
        // 实际业务中可根据用户表中的账号过期时间字段判断，默认返回true（未过期）
        return true;
    }

    /**
     * 账号是否未被锁定
     * Spring Security会检查该方法返回值，若为false则拒绝登录（提示账号被锁定）
     *
     * @return true表示账号未锁定，false表示已锁定
     */
    @Override
    public boolean isAccountNonLocked() {
        // 实际业务中可根据用户表中的锁定状态字段判断（如status=1表示锁定），默认返回true（未锁定）
        return true;
    }

    /**
     * 密码是否未过期
     * Spring Security会检查该方法返回值，若为false则拒绝登录（提示密码过期）
     *
     * @return true表示密码未过期，false表示已过期
     */
    @Override
    public boolean isCredentialsNonExpired() {
        // 实际业务中可根据用户表中的密码过期时间字段判断，默认返回true（未过期）
        return true;
    }

    /**
     * 账号是否启用
     * Spring Security会检查该方法返回值，若为false则拒绝登录（提示账号已禁用）
     *
     * @return true表示账号启用，false表示已禁用
     */
    @Override
    public boolean isEnabled() {
        // 实际业务中可根据用户表中的状态字段判断（如status=0表示正常启用），默认返回true（启用）
        return true;
    }


}